﻿
using Castle.Core.Internal;
using Coldairarrow.Business.Interface;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.Entity.Interface;
using Coldairarrow.Util;
using NetTopologySuite.Index.HPRtree;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;

namespace Coldairarrow.Business.Interface
{
    public class Rep_ProcurementCostInterfaceBusiness : Interface_BaseBusiness, IJob_Business, ITransientDependency
    {
        public List<OL_FilterDTO> Filters { get; set; }
        public Base_InterfaceOption queryOption { get; set; }
        public Base_InterfaceOption insertOption { get; set; }
        public Base_InterfaceOption upDateOption { get; set; }
        public Base_InterfaceOption deleteOption { get; set; }
        public Rep_ProcurementCostInterfaceBusiness()
        {
            this.InterfaceName = "1C产品月采购成本";
            //获取字段的映射关系
            tableField = GetMapField("editRow");
            //索引字段
            Keys = GetKeys("editRow");
            indexFields.Add(Keys.Where(X => X.Type == "K").First().Field);
            //查询过滤条件
            Filters = new List<OL_FilterDTO>();



            //数据库连接
            ConString = JsonSettingHelper.GetSetting("Database:BaseDb:ConnectionString");
            SqlDb = (SqlServerHelper)DbHelperFactory.GetDbHelper(EFCore.Sharding.DatabaseType.SqlServer, ConString);
            //获取此接口的所有API信息
            this.interfaceOption = SqlDb.GetListBySql<Base_InterfaceOption>(@$"SELECT * FROM  Base_InterfaceOption(NOLOCK) WHERE Name='{InterfaceName}' ");
            this.queryOption = this.interfaceOption.Where(o => o.OperateType == "getFilterRows").First();//查询API配置
            this.insertOption = this.interfaceOption.Where(o => o.OperateType == "addRow").First();//新增API配置
            this.upDateOption = this.interfaceOption.Where(o => o.OperateType == "editRow").First();//更行API配置
            this.deleteOption = this.interfaceOption.Where(o => o.OperateType == "deleteRow").First();//删除API配置


            //查询执行前的事件
            BeforeQueryEvent += InterfaceBusiness_BeforeQueryEvent;
            //查询执行中的事件
            OnQueryEvent += InterfaceBusiness_OnQueryEvent;
            //执行非查询请求中的事件
            OnNoQueryEvent += InterfaceBusiness_OnNoQueryEvent;

        }

        /// <summary>
        /// 执行非查询请求中时间
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="noQueryEventArgs"></param>
        private void InterfaceBusiness_OnNoQueryEvent(object sender, NoQueryEventArgs noQueryEventArgs)
        {
            //API请求是否成功
            noQueryEventArgs.Success = noQueryEventArgs.Result["success"].ToString().ToBool();
        }

        /// <summary>
        /// 查询执行前的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="queryEventArgs"></param>
        private void InterfaceBusiness_BeforeQueryEvent(object sender, QueryEventArgs queryEventArgs)
        {
            //执行查询前添加过滤条件
            if (queryEventArgs.Page.Filters.IsNullOrEmpty() && !Filters.IsNullOrEmpty())
            {
                queryEventArgs.Page.Filters = Filters;
            }

        }

        /// <summary>
        /// 查询执行中的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="queryEventArgs"></param>
        private void InterfaceBusiness_OnQueryEvent(object sender, QueryEventArgs queryEventArgs)
        {
            //是否查询完成
            if (queryEventArgs.Result["data"]["rows"].ToList().Count == 0)
            {
                queryEventArgs.Page.Complete = true;
            }
            //向总行中添加新的行
            queryEventArgs.Rows.AddRange(queryEventArgs.Result["data"]["rows"].ToList());
            //获取总页数
            queryEventArgs.Page.Total = queryEventArgs.Result["data"]["total"].ToString().ToInt();
            //获取查询成功标志
            queryEventArgs.Success = queryEventArgs.Result["success"].ToString().ToBool();
        }


        /// <summary>
        /// 执行增删改查业务
        /// </summary>
        public async void ExecuteInterface()
        {

            try
            {
                //获取不筛选的贷方会记科目
                List<string> unCredit = queryOption.Notes.Split(',').ToList();

                //生成几月的采购成本
                string dateTo = DateTime.Now.AddMonths(-queryOption.ExcInterval).ToString("yyyy-MM") + "-01";
                //获取金蝶俄罗斯汇率
                SqlDb._conStrings[0] = JsonSettingHelper.GetSetting("Database:BaseDb:K3ConnectionString");
                List<View_Rate> KD_Rate = SqlDb.GetListBySql<View_Rate>(@$"SELECT * FROM  V_WW_BD_Rate(NOLOCK) WHERE 汇率类型 = '俄罗斯专用' ");

                //获取序时账列表
                Rep_ChronologicalAccountInterfaceBusiness Rep_ChronologicalAccount = new Rep_ChronologicalAccountInterfaceBusiness();
                Rep_ChronologicalAccount.Filters.Clear();
                Rep_ChronologicalAccount.Filters.Add(
                //13:>,14>=15:<,16<=
                new OL_FilterDTO() { ControlId = "67d11f12cd44971bbf2bebf5", DataType = 15, SpliceType = 1, FilterType = 14, Value = dateTo }//FDATE字段过滤日开
            );
                Rep_ChronologicalAccount.Filters.Add(
                //13:>,14>=15:<,16<=
                new OL_FilterDTO() { ControlId = "67d0fcbdcd44971bbf2842af", DataType = 2, SpliceType = 1, FilterType = 2, Value = "41.01" }//借方的会记科目
            );
                List<Rep_ChronologicalAccount> Rep_ChronAccount = await Rep_ChronologicalAccount.QueryAsync<Rep_ChronologicalAccount>(Rep_ChronologicalAccount.queryOption, Rep_ChronologicalAccount.tableField, Rep_ChronologicalAccount.SqlDb);
                List<Rep_ChronologicalAccount> lastMonthCost = Rep_ChronAccount.Where(x => !unCredit.Any(y => y.Contains(x.creditAccountingSubject))).ToList().DeepClone();
                //获取费用来源是付款单的费用,根据物料名称，时间分组
                var payList = Rep_ChronAccount.Where(x => x.document.Contains("Поступление (акт, накладная, УПД)") && x.Amount.ToDouble() != 0).GroupBy(x => x.debitAnalytic1 + x.date.ToDateTime().ToString("yyyy-MM"));

                //计算每个物料的成本价格
                List<Rep_ProcurementCost> sourceData = new List<Rep_ProcurementCost>();
                foreach (var item1 in payList)
                {
                    Rep_ProcurementCost cost = new Rep_ProcurementCost();
                    if (item1.First().debitAnalytic1 == "Котел газовый  MIZUDO CLASSIC B M24H (24 кВт, 2 Т/O)")
                    {

                        var ww = "";

                    }

                    //使用每组的第一项来查询产品对应月份的所有费用项
                    var first = item1.First();
                    var costList = Rep_ChronAccount.Where(x => x.debitAnalytic1 == first.debitAnalytic1 && x.date.ToDateTime().ToString("yyyy-MM") == first.date.ToDateTime().ToString("yyyy-MM") && x.Amount.ToDouble() != 0 && !unCredit.Any(y => y.Contains(x.creditAccountingSubject)));
                    //获取同时间的金蝶汇率
                    var KD_rate_ = KD_Rate.Where(x => x.生效时间.ToDateTime().ToString("yyyy-MM-dd").ToDateTime() <= first.date.ToDateTime().ToString("yyyy-MM-dd").ToDateTime() && first.date.ToDateTime() <= x.失效时间.ToDateTime().ToString("yyyy-MM-dd").ToDateTime());
                    var rate = !KD_rate_.IsNullOrEmpty() && KD_rate_.Count() > 0 ? KD_rate_.First().间接汇率.ToDouble() : 0;

                    //var temp = item1.Where(x => x.creditAmountInCurrency.ToDouble() == 0);
                    //供应商币别为人民币的金额直接相加
                    var costList_CNY = costList.Where(x => x.CurrencyCredit == "CNY" && x.debitCount.ToDouble() != 0);
                    double Currency_CNY = costList_CNY.IsNullOrEmpty() && costList_CNY.Count() == 0 ? 0 : costList_CNY.Sum(x => x.creditAmountInCurrency.ToDouble());
                    //供应商币别为俄币的金额乘上汇率相加
                    var costList_Other = costList.Where(x => x.CurrencyCredit != "CNY" || (x.CurrencyCredit == "CNY" && x.debitCount.ToDouble() == 0));
                    double Currency_Cost = costList_Other.Sum(x => x.Amount.ToDouble()) / rate;
                    //获取总金额
                    double currency = Currency_CNY + Currency_Cost;
                    //获取总数量
                    double count = costList.Sum(x => x.debitCount.ToDouble());

                    cost.cost = (currency / count).ToString("F2");
                    cost.amount = currency.ToString("F2");
                    cost.count = count.ToString("F2");
                    cost.date = first.date.ToDateTime().ToString("yyyy-MM");
                    cost.rate = rate.ToString("F4");
                    cost.productName = first.debitAnalytic1;
                    cost.supplierName = first.creditAnalytic1;
                    cost.rep_ChronologicalAccount = string.Join(',', costList.OrderBy(x => x.RowId).Select(x => x.RowId));
                    cost.id = cost.productName + cost.date;
                    sourceData.Add(cost);
                    costList.ForEach(x => lastMonthCost.RemoveAll(y => y.RowId == x.RowId));
                }
                //没有采购入库产生的费用，有可能是上月的物料本月结算
                foreach (var item1 in lastMonthCost.GroupBy(x => x.debitAnalytic1 + x.date.ToDateTime().ToString("yyyy-MM")))
                {
                    var first = item1.First();
                    //获取同时间的金蝶汇率
                    var KD_rate_ = KD_Rate.Where(x => x.生效时间.ToDateTime().ToString("yyyy-MM-dd").ToDateTime() <= first.date.ToDateTime().ToString("yyyy-MM-dd").ToDateTime() && first.date.ToDateTime() <= x.失效时间.ToDateTime().ToString("yyyy-MM-dd").ToDateTime());
                    var rate = !KD_rate_.IsNullOrEmpty() && KD_rate_.Count() > 0 ? KD_rate_.First().间接汇率.ToDouble() : 0;
                    //获取原有项
                    var purCostItem = sourceData.Where(x => x.productName == first.debitAnalytic1 && x.date == first.date);
                    if (!purCostItem.IsNullOrEmpty() && purCostItem.Count() > 0)
                    {
                        //将费用叠加到原有产品上并计算单价
                        var purCost = purCostItem.First();//原有的项
                        var cost = item1.Sum(x => x.Amount.ToDouble() / rate);//增加的费用
                        var qty = purCost.count.ToDouble() + item1.Sum(x => x.debitCount.ToDouble());//增加的数量;
                        purCost.amount = (purCost.amount.ToDouble() + cost).ToString();
                        if ((!purCost.count.IsNullOrEmpty() && purCost.count.ToDouble() != 0) || (!qty.IsNullOrEmpty() && qty != 0))
                        {

                            purCost.count = qty + purCost.count.ToDouble().ToString("F2");
                            purCost.cost = (purCost.amount.ToDouble() / purCost.count.ToDouble()).ToString();
                        }
                    }
                    else
                    {

                        Rep_ProcurementCost cost = new Rep_ProcurementCost();
                        cost.count = item1.Sum(x => x.debitCount.ToDouble()).ToString("F2");
                        cost.amount = (item1.Sum(x => x.Amount.ToDouble()) / rate).ToString("F2");//增加的费用
                        cost.cost = cost.count.ToDouble() == 0 ? "0" : (cost.amount.ToDouble() / cost.count.ToDouble()).ToString("F2");
                        cost.date = first.date.ToDateTime().ToString("yyyy-MM");
                        cost.rate = rate.ToString("F4");
                        cost.productName = first.debitAnalytic1;
                        cost.supplierName = first.debitAnalytic2;
                        cost.rep_ChronologicalAccount = string.Join(',', item1.OrderBy(x => x.RowId).Select(x => x.RowId));
                        cost.id = cost.productName + cost.date;
                        sourceData.Add(cost);
                    }
                }

                //获取目标数据
                List<Rep_ProcurementCost> targetData = new List<Rep_ProcurementCost>();//目标据集合
                                                                                       //var fDate = sourceData.OrderBy(x => x.date.ToDateTime()).First().date.ToDateTime().ToString("yyyy-MM-dd");
                var fDate = sourceData.OrderBy(x => x.date.ToDateTime()).First().date.ToDateTime().ToString("yyyy-MM");
                Filters.Clear();
                Filters.Add(
                //13:>,14>=15:<,16<=
                new OL_FilterDTO() { ControlId = "67d932aacd44971bbfdcf804", DataType = 15, SpliceType = 1, FilterType = 14, Value = fDate }//FDATE字段过滤日开
            );
                targetData = await QueryAsync<Rep_ProcurementCost>(queryOption, tableField, SqlDb);

                //将ID相同的值覆盖
                foreach (var item1 in targetData)
                {
                    //将关联表的ID拼接成对应的格式
                    List<string> table = item1.rep_ChronologicalAccount.ToObject<List<string>>();
                    var idList = table.OrderBy(x => x);
                    item1.rep_ChronologicalAccount = string.Join(",", idList);
                    //将ID相同的项，填写物料
                    var list = sourceData.Where(x => x.id == item1.id);
                    if (!list.IsNullOrEmpty() || list.Count() > 0)
                    {
                        sourceData.ForEach(x =>
                        {
                            if (x.id == item1.id)
                            {
                                x.productNo = item1.productNo;
                            }
                        });


                    }
                }
                if (this.State > 0 && sourceData.Count > 0)
                {
                    //更新
                    #region
                    List<Rep_ProcurementCost> updataItem = sourceData.Intersect(targetData, new ComparerFromKeys<Rep_ProcurementCost>(Keys, "RowId")).ToList();//获取交集(更新项)
                    List<OL_RowDTO> updataData = ConvertOL_Row(updataItem, tableField);//需要更新的数据集合
                    ExecuteNoQuery<OL_RowDTO>(updataData, upDateOption, SqlDb);//执行更新
                    #endregion

                    //新增
                    #region
                    List<Rep_ProcurementCost> insertItem = sourceData.Except(targetData, new ComparerFromKey<Rep_ProcurementCost>(indexFields.First(), "RowId")).ToList();//获取源数据对目标数据的差集(新增项)
                    List<OL_RowDTO> insertData = ConvertOL_Row(insertItem, tableField);//需要新增的数据集合
                    ExecuteNoQuery<OL_RowDTO>(insertData, insertOption, SqlDb);//执行插入行
                    #endregion

                    //删除
                    #region
                    List<Rep_ProcurementCost> deleteItem = targetData.Except(sourceData, new ComparerFromKey<Rep_ProcurementCost>(indexFields.First(), "RowId")).ToList();//获取目标数对据源数据的差集(删除项)
                    List<OL_RowDTO> deleteData = ConvertOL_Row(deleteItem, tableField);//需要删除的数据集合
                    ExecuteNoQuery<OL_RowDTO>(deleteData, deleteOption, SqlDb);//执行删除行
                    #endregion
                }
            }


            catch (Exception ex)
            {
                AddLog(SqlDb, ex.Message, InterfaceName, "erro", "");
            }
        }

        /// <summary>
        /// 将源数据根据字典映射关系转换成OL_RowDTO
        /// </summary>
        /// <typeparam name="T">源数据</typeparam>
        /// <param name="sourceData">源数据</param>
        /// <param name="map">Key为目标字段名称，Value为源字段名称</param>
        /// <returns></returns>
        public List<OL_RowDTO> ConvertOL_Row<T>(List<T> sourceData, Dictionary<string, string> map)
        {
            List<OL_RowDTO> list = new List<OL_RowDTO>();
            object rowId;
            foreach (var item in sourceData)
            {
                rowId = item.GetPropertyValue("RowId");
                //需要新增的数据
                OL_RowDTO row = new OL_RowDTO() { RowId = rowId.IsNullOrEmpty() ? null : rowId.ToString(), Controls = new List<Control>() };
                foreach (var c in map)
                {
                    //获取字段的键值做判断
                    var field = Keys.Where(x => x.TField == c.Key).ToList();
                    string isKey = "";
                    if (field.Count > 0) isKey = field.First().Type;
                    //判断对象的字段是否存在
                    if (item.ContainsProperty(c.Value) && isKey != "N")
                    {
                        //存在则添加数据
                        row.Controls.Add(new Control() { ControlId = c.Key, Value = item.GetPropertyValue(c.Value) });
                    }
                }
                list.Add(row);
            }
            return list;
        }

        /// <summary>
        /// 任务
        /// </summary>
        public void Job()
        {
            ExecuteInterface();
        }
    }

}
